package com.linkoog.devtools.everywhere.docs;

import com.intellij.icons.AllIcons;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.actions.searcheverywhere.AbstractGotoSEContributor;
import com.intellij.ide.util.gotoByName.FilteringGotoByModel;
import com.intellij.navigation.ChooseByNameContributor;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.util.ArrayUtilRt;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.Icon;

import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class DocSearchContributor extends AbstractGotoSEContributor {

    private final ChooseByNameContributor contributor;

    protected DocSearchContributor(@NotNull AnActionEvent event) {
        super(event);

        this.contributor = new ChooseByNameContributor() {
            private final Map<String, SearchTitlesProvider.TitleInfo> results = new ConcurrentHashMap();

            @NotNull
            public String[] getNames(Project project, boolean includeNonProjectItems) {
                this.results.clear();
                this.results.putAll(SearchTitlesProvider.getInstance(project).getItems());
                return this.results.keySet().toArray(ArrayUtilRt.EMPTY_STRING_ARRAY);
            }


            @NotNull
            public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
                return new NavigationItem[]{
                        new SearchResultNavigationItem(this.results.get(name))
                };
            }
        };
    }

    private static class SearchResultNavigationItem implements NavigationItem {
        final Presentation presentation;

        SearchResultNavigationItem(SearchTitlesProvider.TitleInfo item) {
            this.presentation = new Presentation(item);
        }


        @Nullable
        public String getName() {
            return this.presentation.item.title;
        }


        @Nullable
        public ItemPresentation getPresentation() {
            return this.presentation;
        }


        public void navigate(boolean requestFocus) {
            BrowserUtil.browse(this.presentation.item.url);
        }


        public boolean canNavigate() {
            return true;
        }


        public boolean canNavigateToSource() {
            return false;
        }

    }

    private static class Presentation implements ItemPresentation {
        private final SearchTitlesProvider.TitleInfo item;

        Presentation(SearchTitlesProvider.TitleInfo item) {
            this.item = item;
        }


        @Nullable
        public String getPresentableText() {
            return this.item.title;
        }


        @Nullable
        public String getLocationString() {
            return "topic".equals(this.item.type) ? "help article" : ("in article \"" + this.item.articleTitle + "\"");
        }


        @Nullable
        public Icon getIcon(boolean unused) {
            return AllIcons.Actions.Help;
        }
    }

    @NotNull
    protected FilteringGotoByModel<?> createModel(@NotNull Project project) {
        return new FilteringGotoByModel<Object>(project, new ChooseByNameContributor[]{this.contributor}) {
            @Nullable
            protected Object filterValueFor(NavigationItem item) {
                return (item instanceof SearchResultNavigationItem) ? item : null;
            }


            @Nls(capitalization = Nls.Capitalization.Sentence)
            public String getPromptText() {
                return "Search article, procedure and chapter titles";
            }


            @NotNull
            public String getNotInMessage() {
                return getNotFoundMessage();
            }


            @NotNull
            public String getNotFoundMessage() {
                return "No matching results";
            }


            @Nullable
            public String getCheckBoxName() {
                return null;
            }


            public boolean loadInitialCheckBoxState() {
                return false;
            }


            public void saveInitialCheckBoxState(boolean state) {
            }


            @NotNull
            public String[] getSeparators() {
                return new String[0];
            }


            @Nullable
            public String getFullName(@NotNull Object element) {
                return ((NavigationItem) element).getName();
            }


            public boolean willOpenEditor() {
                return false;
            }
        };
    }


    @NotNull
    @Nls
    public String getGroupName() {
        return "Help Articles9";
    }


    public int getSortWeight() {
        return 999;
    }


    public boolean isEmptyPatternSupported() {
        return false;
    }
}
